#include "HttpClient.hpp"

#include <QEventLoop>
#include <QTimer>

HttpClient::HttpClient(QObject *parent)
    : QObject(parent)
{
}

HttpClient::~HttpClient()
{
    lazyDeleteNetworkReply();
}

int HttpClient::syncPost(const QNetworkRequest& request, const QByteArray &param,
                         QNetworkReply::NetworkError &networkError, QByteArray &response,
                         int timeout /*= 6000*/)
{
    HttpClientError httpClientResult = HCE_OK;

    while(true)
    {
        HttpClient httpClient;
        httpClient.setConnectTimeout(timeout);

        QNetworkReply *reply = httpClient.post(request, param);
        if(reply == NULL)
        {
            httpClientResult = HCE_INTERNAL_ERROR;
            break;
        }

        QTimer timer;
        QMetaObject::Connection timerConn;

        QEventLoop eventLoop;

        QMetaObject::Connection netConn = QObject::connect(reply, &QNetworkReply::finished, &eventLoop, [&]()
        {
            disconnect(timerConn);

            if(timer.isActive())
            {
                timer.stop();
            }

            networkError = reply->error();
            if(networkError != QNetworkReply::NoError)
            {
                httpClientResult = HCE_HTTP_ERROR;
            }

            response = reply->readAll();

            eventLoop.quit();
        });

        timerConn = QObject::connect(&timer, &QTimer::timeout, [&]()
        {
            disconnect(netConn);

            if(timer.isActive())
            {
                timer.stop();
            }

            if(reply && !reply->isFinished())
            {
                reply->abort();
            }

            httpClientResult = HCE_TIMEOUT;

            eventLoop.quit();
        });

        timer.start(timeout);
        eventLoop.exec();

        break;
    }

    return httpClientResult;
}

int HttpClient::syncPost(const QNetworkRequest& request, QHttpMultiPart *multiPart,
                         QNetworkReply::NetworkError &networkError, QByteArray &response,
                         int timeout/* = 6000*/)
{
    HttpClientError httpClientResult = HCE_OK;

    while(true)
    {
        HttpClient httpClient;
        httpClient.setConnectTimeout(timeout);

        QNetworkReply *reply = httpClient.post(request, multiPart);
        if(reply == NULL)
        {
            httpClientResult = HCE_INTERNAL_ERROR;
            break;
        }

        QTimer timer;
        QMetaObject::Connection timerConn;

        QEventLoop eventLoop;

        QMetaObject::Connection netConn = QObject::connect(reply, &QNetworkReply::finished, &eventLoop, [&]()
        {
            disconnect(timerConn);

            if(timer.isActive())
            {
                timer.stop();
            }

            networkError = reply->error();
            if(networkError != QNetworkReply::NoError)
            {
                httpClientResult = HCE_HTTP_ERROR;
            }

            response = reply->readAll();

            eventLoop.quit();
        });

        timerConn = QObject::connect(&timer, &QTimer::timeout, [&]()
        {
            disconnect(netConn);

            if(timer.isActive())
            {
                timer.stop();
            }

            if(reply && !reply->isFinished())
            {
                reply->abort();
            }

            httpClientResult = HCE_TIMEOUT;

            eventLoop.quit();
        });

        timer.start(timeout);
        eventLoop.exec();

        break;
    }

    return httpClientResult;
}

int HttpClient::syncGet(const QNetworkRequest& request,
                        QNetworkReply::NetworkError &networkError, QByteArray &response,
                        int timeout /*= 6000*/)
{
    HttpClientError httpClientResult = HCE_OK;

    while(true)
    {
        HttpClient httpClient;
        httpClient.setConnectTimeout(timeout);

        QNetworkReply *reply = httpClient.get(request);
        if(reply == NULL)
        {
            httpClientResult = HCE_INTERNAL_ERROR;
            break;
        }

        QTimer timer;
        QMetaObject::Connection timerConn;

        QEventLoop eventLoop;

        QMetaObject::Connection netConn = QObject::connect(reply, &QNetworkReply::finished, &eventLoop, [&]()
        {
            disconnect(timerConn);

            if(timer.isActive())
            {
                timer.stop();
            }

            networkError = reply->error();
            if(networkError != QNetworkReply::NoError)
            {
                httpClientResult = HCE_HTTP_ERROR;
            }

            response = reply->readAll();

            eventLoop.quit();
        });

        timerConn = QObject::connect(&timer, &QTimer::timeout, [&]()
        {
            disconnect(netConn);

            if(timer.isActive())
            {
                timer.stop();
            }

            if(reply && !reply->isFinished())
            {
                reply->abort();
            }

            httpClientResult = HCE_TIMEOUT;

            eventLoop.quit();
        });

        timer.start(timeout);
        eventLoop.exec();

        break;
    }

    return httpClientResult;
}
